#include "taihesen_rfid.hpp"

#include "devices/mcu_device.hpp"

#include <log/log.hpp>
#include <commons/util/util.hpp>
#include <commons/type/datetime.hpp>
#include <commons/sync_async/async_timer.hpp>

const static uint8_t HEAD_FLAG = 0xaa;
const static uint8_t TAIL_FLAG = 0xbb;

const static int RFID_REPORT_INTERVAL_MS = 50;    // 设备上报间隔 ms
const static int TRIGGER_TIMEOUT_MS      = 130;   // 超时阈值(大于2.5个上报周期) ms
const static int CONN_TIMEOUT_MS         = 3000;  // 通讯超时 ms

namespace sros::device::detail
{
    TaiHeSenRfid::TaiHeSenRfid(const uint16_t &index, std::shared_ptr<McuDevice> mcu)
        : rfid_impl()
        , timer_(nullptr)
        , mcu_(mcu)
        , last_trigger_time_(0)
        , last_recv_time_(0)
        , is_rfid_on_(false)
        , last_conn_state_(true)
    {
        uart_index_ = index;
    }

    void TaiHeSenRfid::init()
    {
        info_.datetime = "Unkown";
        info_.hardware_version = "Unkown";
        info_.software_version = "Unkown";
        info_.manufacturer = "上海森目";
        info_.model = "泰合森";

        last_recv_time_.store(DateTime::currentDateTime().toMSecsSinceEpoch());

        DataUp data{.id = -1, .detecting = false, .error = 0, .state = DEV_UNINIT};
        set_data_up(data);

        if (timer_ == nullptr)
        {
            timer_ = std::make_shared<async::Timer>();
        }
    }

    void TaiHeSenRfid::run()
    {
        auto data = data_up();
        data.state = DEV_INITING;
        set_data_up(data);
        
        if (timer_)
        {
            timer_->safe_start(10, 20, 0, [this](std::size_t times)
                               { on_timer_trigger_(times); });
        }
    }

    void TaiHeSenRfid::close()
    {
        if (timer_)
        {
            timer_->safe_stop();
            timer_->safe_clear();
            timer_ = nullptr;
        }
    }

    void TaiHeSenRfid::parse(const device::proto::RspUartMsg &uart_msg)
    {
        if (uart_msg.index != uart_index_)
        {
            return;
        }

        auto data = data_up();

        last_recv_time_.store(DateTime::currentDateTime().toMSecsSinceEpoch());

        if (uart_msg.buffer.size() < 6)
        {
            if (event_cb_)
            {
                event_cb_(EV_RFID_ERORR, 1, "invalid data");
            }

            data.state = DEV_ERORR;
            set_data_up(data);

            LOG_WARN("uart msg size is less than 6, invalid data:{}", util::hex_to_string(uart_msg.buffer));
            return;
        }

        if (uart_msg.buffer.at(0) != HEAD_FLAG || uart_msg.buffer.at(uart_msg.buffer.size()-1) != TAIL_FLAG)
        {
            if (event_cb_)
            {
                event_cb_(EV_RFID_ERORR, 1, "invalid data");
            }

            data.state = DEV_ERORR;
            set_data_up(data);

            LOG_WARN("header or tail flag is not equal 0xaa or 0xbb, invalid data:{}", util::hex_to_string(uart_msg.buffer));
            return;
        }

        uint8_t addr = uart_msg.buffer.at(1);
        uint8_t len = uart_msg.buffer.at(2);
        uint8_t cmd = uart_msg.buffer.at(3);
        uint8_t crc = uart_msg.buffer.at(len+3);

        uint8_t calc_crc = 0;
        for (int i = 1; i <= len + 2; i++)
        {
            calc_crc ^= uart_msg.buffer.at(i);
        }

        if (crc != calc_crc)
        {
            if (event_cb_)
            {
                event_cb_(EV_RFID_ERORR, 1, "invalid data");
            }

            data.state = DEV_ERORR;
            set_data_up(data);

            LOG_WARN("calc_crc({:x}) is not equal crc({:x}), invalid data:{}", 
                     (uint16_t)calc_crc, (uint16_t)crc, util::hex_to_string(uart_msg.buffer));
            return;
        }
        
        data.state = DEV_RUNNING;
        
        if (cmd == 0x11 && len >= 2)
        {
            // 收到有效数据，更新时间戳
            last_trigger_time_.store(DateTime::currentDateTime().toMSecsSinceEpoch());

            data.id = uart_msg.buffer.at(5);
            data.detecting = true;
            LOG_INFO("[RFID] detected: {}", data.id);
        }
        else
        {
 
        }

        set_data_up(data);
    }

    void TaiHeSenRfid::on_timer_trigger_(std::size_t times)
    {
        if (times % 25 == 0) // 500ms
        {
            // 多协议自动上传设置 指令
            const static std::vector<uint8_t> data = {0x02, 0x00, 0x07, 0x4a, 0xcf, 0xa2, 
                                                      0x00, 0x00, 0x02, 0x0d, 0x2f, 0x03};

            auto ret = send_uart_msg_(data);
            if (!ret.v)
            {
                LOG_WARN("send uart msg failed, {}", ret.msg);
            }
        }
        
        auto data = data_up();

        uint64_t current_time = DateTime::currentDateTime().toMSecsSinceEpoch();
        uint64_t time_since_last_recv = current_time - last_recv_time_.load();
        bool current_conn_state = (time_since_last_recv <= CONN_TIMEOUT_MS);

        // 正常→断连
        if (!current_conn_state && last_conn_state_.load())
        {
            LOG_WARN("[RFID] disconnect, {} - {} = {}", current_time, last_recv_time_.load(), time_since_last_recv);
            data.state = DEV_DISCONNECT;
            if (event_cb_)
            {
                event_cb_(EV_RFID_DISCONNECT, 0, "RFID disconnect");  // 触发标签出现事件
            }
        }

        last_conn_state_.store(current_conn_state);

        // 计算距离上次触发的时间
        uint64_t time_since_last_trigger = current_time - last_trigger_time_.load();
        bool current_rfid_on = (time_since_last_trigger <= TRIGGER_TIMEOUT_MS);
    
        // 检测状态变化，触发相应事件
        if (!is_rfid_on_.load() && current_rfid_on) 
        {
            LOG_INFO("[RFID] ON id:{}", data.id);

            if (event_cb_)
            {
                event_cb_(EV_RFID_ON, data.id, "RFID ON");  // 触发标签出现事件
            }
        }
        else if (is_rfid_on_.load() && !current_rfid_on) 
        {
            LOG_INFO("[RFID] OFF id:{}", data.id);
            
            if (event_cb_)
            {
                event_cb_(EV_RFID_OFF, data.id, "RFID OFF");  // 触发标签离开事件（即进入抑制状态）
            }
        }

        // 更新状态变量
        is_rfid_on_.store(current_rfid_on);

        // 更新数据状态
        data.detecting = current_rfid_on;
        set_data_up(data);
    }

    RetBool TaiHeSenRfid::send_uart_msg_(const std::vector<uint8_t> &data)
    {
        auto uart_status_list = mcu_->uarts_status();
        auto it = uart_status_list.find(uart_index());
        if (it == uart_status_list.end())
        {
            return {false, "can not find this uart index"};
        }
        if (it->second.active != 1 || it->second.error != 0)
        {
            return {false, "this uart channel is not active"};
        }

        proto::ReqUartMsg req;
        req.index = uart_index();
        req.data = data;
        return mcu_->send_uart_msg(req);
    }
}